package 代码题.动态规划题目;

/**
 * 多重背包问题
 * <p>
 * 一个背包，多个物品，每个物品有自己的价值，重量，最后还有数量限制。求背包能够获得最大利润
 * <p>
 * 思路：将多重背包转化为01背包
 * 状态转移方程：dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * weight[i]] + k * value[i]);
 * dp[i][j]表示的是在容量为j的情况下选取第i种物品的最大value值。这里注意是“种”不是“个”
 */
public class DP_Multi {

    /**
     * 一个背包，重量为5
     * 4个物品，他们分别的价值，重量，数量关系如下
     * (2, 1, 3)
     * (4, 2, 1)
     * (4, 3, 3)
     * (5, 4, 2)
     * <p>
     * 输出的最大价值：10。分别取3个第一物品和1个第二物品
     *
     * @param args
     */
    public static void main(String[] args) {
        int[][] dp = new int[5][6];  //默认初始化二维数组为0.需要增加一个辅助行和辅助列
        int[] value = new int[]{0, 2, 4, 4, 5};
        int[] weight = new int[]{0, 1, 2, 3, 4};
        int[] count = new int[]{0, 3, 1, 3, 2};

        for (int i = 1; i < 5; i++) {
            for (int j = 5; j >= 0; j--) {
                //这里转化为完全背包了
                for (int k = 0; k <= count[i]; k++) {
                    if (j >= k * weight[i]) {
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * weight[i]] + k * value[i]);
                    }
                }
            }
        }
        System.out.println(dp[4][5]);

        //打印最值得二维数组
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 6; j++) {
                System.out.print(dp[i][j]+"\t");
            }
            System.out.println();
        }
    }

}
